home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 June / CHIP Haziran 2001.iso / prog / haziran / 19 / setup.exe / data.z / pci_dma.c < prev    next >
C/C++ Source or Header  |  2001-04-11  |  8KB  |  262 lines

  1. ////////////////////////////////////////////////////////////////
  2. // File - PCI_DMA.C
  3. //
  4. // This is a skeleton driver for a PCI card with Bus Master DMA.
  5. // The driver implemets PCI detection, accessing memory mapped 
  6. // ranges on the card, and interrupt handler installation.
  7. // 
  8. // It is recommended to take a look at real-world samples of 
  9. // PCI Bus Master DMA, in /windrvr/amcc/lib/amcclib.c and 
  10. // /windrvr/v3/lib/pbclib.c.
  11. //
  12. ////////////////////////////////////////////////////////////////
  13.  
  14. #include "../../include/windrvr.h"
  15. #include <stdio.h>
  16.  
  17. // put your vendor_id & device_id here
  18. enum {MY_VENDOR_ID = 0x1201};
  19. enum {MY_DEVICE_ID = 0x0001};
  20.  
  21. // put the offset of the card's register for programing DMA here
  22. enum {MY_REG_DMA_STATUS = 0x10};
  23. enum {MY_REG_DMA_PAGES = 0x100};
  24.  
  25. void MY_CardMainDriver()
  26. {
  27.     // put your device driver code here
  28. }
  29.  
  30.  
  31. /////////////////////////////////////
  32. // global variables section G_xxxx
  33. /////////////////////////////////////
  34. enum {INVALID_RES = 0xffff};
  35.  
  36. HANDLE hWD;
  37. WD_CARD_REGISTER G_cardReg;
  38.  
  39. // index to resource in card of memory region & interrupt
  40. // if you have more than one memory region, interrupt or have an IO range,
  41. // add more indexes here, and locate them in IO_DetectCardElements() function.
  42. DWORD G_resMemory;
  43. // base address for memory mapped region
  44. DWORD G_baseMemory;
  45. DWORD G_baseMemoryTrns;
  46.  
  47. void IO_Open()
  48. {
  49.     WD_VERSION ver;
  50.  
  51.     hWD = INVALID_HANDLE_VALUE;
  52.     hWD = WD_Open();
  53.     // Check whether handle is valid and version OK
  54.     if (hWD==INVALID_HANDLE_VALUE) 
  55.     {
  56.         printf("Failed opening " WD_PROD_NAME " device\n");
  57.         exit(1);
  58.     }
  59.     BZERO(ver);
  60.     WD_Version(hWD,&ver);
  61.     if (ver.dwVer<WD_VER) 
  62.     {
  63.         printf("Incorrect " WD_PROD_NAME " version\n");
  64.         WD_Close(hWD);
  65.         exit(1);
  66.     }
  67.  
  68.     G_cardReg.hCard = 0;
  69. }
  70.  
  71. // IO_DetectCardElements() scans the card recourses (Interrupts, IO & memory mapped regions)
  72. // and sets IO_ResInterrupt & IO_ResMemory to point to the correct element number
  73. void IO_DetectCardElements()
  74. {
  75.     DWORD i;
  76.  
  77.     G_resMemory = INVALID_RES;
  78.  
  79.     for (i=0; i<G_cardReg.Card.dwItems; i++)
  80.     {
  81.         switch(G_cardReg.Card.Item[i].item)
  82.         {
  83.         case ITEM_INTERRUPT:
  84.             printf("error - Card has an Interrupt\n");
  85.             exit(1);
  86.             break;
  87.         case ITEM_MEMORY:
  88.             if (G_resMemory==INVALID_RES) 
  89.                 G_resMemory = i;
  90.             else
  91.             {
  92.                 printf("error - Card has more than one memory region\n");
  93.                 exit(1);
  94.             }
  95.             break;
  96.         case ITEM_IO:
  97.             printf("error - Card has an IO ragne\n");
  98.             exit(1);
  99.             break;
  100.         }
  101.     }
  102.  
  103.     if (G_resMemory==INVALID_RES)
  104.     {
  105.         printf("Memory region not found\n");
  106.         exit(1);
  107.     }
  108. }
  109.  
  110. // IO_DetectCard() scans the PCI bus & detect the card
  111. void IO_DetectCard()
  112. {
  113.     WD_PCI_SCAN_CARDS pciScan;
  114.     WD_PCI_CARD_INFO pciCardInfo;
  115.  
  116.     BZERO(pciScan);
  117.     pciScan.searchId.dwVendorId = MY_VENDOR_ID;
  118.     pciScan.searchId.dwDeviceId = MY_DEVICE_ID;
  119.     WD_PciScanCards (hWD, &pciScan);
  120.     if (pciScan.dwCards==0) // Found at least one card
  121.     {
  122.         printf("Could not find PCI card\n");
  123.         exit(1);
  124.     }
  125.  
  126.     BZERO(pciCardInfo);
  127.     pciCardInfo.pciSlot = pciScan.cardSlot[0];
  128.     WD_PciGetCardInfo (hWD, &pciCardInfo);
  129.         
  130.     // the info for Card comes from WD_PciGetCardInfo() 
  131.     // for PCI cards. for ISA cards the information has to be
  132.     // set by the user (IO/memory address & interrupt number).
  133.     BZERO(G_cardReg);
  134.     G_cardReg.Card = pciCardInfo.Card;
  135.     IO_DetectCardElements();
  136.     G_cardReg.fCheckLockOnly = FALSE;
  137.     WD_CardRegister (hWD, &G_cardReg);
  138.     if (G_cardReg.hCard==0)
  139.     {
  140.         printf ("Failed locking device\n");
  141.         exit(1);
  142.     }
  143.  
  144.     G_baseMemory = G_cardReg.Card.Item[G_resMemory].I.Mem.dwUserDirectAddr;
  145.     G_baseMemoryTrns = G_cardReg.Card.Item[G_resMemory].I.Mem.dwTransAddr;
  146. }
  147.  
  148. void IO_Close()
  149. {
  150.     // unregister card
  151.     if (G_cardReg.hCard) 
  152.         WD_CardUnregister(hWD, &G_cardReg);
  153.  
  154.     // close WinDriver
  155.     WD_Close(hWD);
  156. }
  157.  
  158. // performs a single 32 bit read from memory mapped range
  159. DWORD IO_Read32BitRegister(DWORD dwAddr)
  160. {
  161.     PDWORD pDW = (PDWORD) (G_baseMemory + dwAddr);
  162.     return *pDW;
  163. }
  164.  
  165. // performs a single 32 bit write to memory mapped range
  166. void IO_Write32BitRegister(DWORD dwAddr, DWORD dwData)
  167. {
  168.     PDWORD pDW = (PDWORD) (G_baseMemory + dwAddr);
  169.     *pDW = dwData;
  170. }
  171.  
  172. // transfer data to/from PCI card using bus-master DMA.
  173. // pBuffer if the data to transfer (or to receive data), dwBytes - size of data
  174. // fIsRead is TRUE for read (PCI card --> system memory), or FALSE for write ( memory --> PCI card)
  175. // addr local address on PCI card
  176. void IO_DMATransferBuffer(PVOID pBuffer, DWORD dwBytes, BOOL fIsRead, DWORD dwAddr)
  177. {
  178.     WD_DMA dma;
  179.     DWORD i;
  180.     DWORD dwSumBytes;
  181.  
  182.     BZERO(dma);
  183.     dma.pUserAddr = pBuffer;
  184.     dma.dwBytes = dwBytes;
  185.     dma.dwOptions = 0;
  186.  
  187.     // lock region in memory & get page list
  188.     WD_DMALock(hWD,&dma);
  189.  
  190.     // program page transfer list on PCI bus master card
  191.     dwSumBytes = 0;
  192.     for (i=0; i<dma.dwPages; i++)
  193.     {
  194.         IO_Write32BitRegister(MY_REG_DMA_PAGES + i*12 + 0, (DWORD) dma.Page[i].pPhysicalAddr);
  195.         IO_Write32BitRegister(MY_REG_DMA_PAGES + i*12 + 4, dwAddr + dwSumBytes);
  196.         IO_Write32BitRegister(MY_REG_DMA_PAGES + i*12 + 8, dma.Page[i].dwBytes);
  197.         dwSumBytes += dma.Page[i].dwBytes;
  198.     }
  199.     
  200.     // write the number of pages to transfer and direction of transfer
  201.     IO_Write32BitRegister(MY_REG_DMA_STATUS, dma.dwPages | (fIsRead ? 0x1000 : 0));
  202.  
  203.     // wait for for status register to indicate transfer compleate here.
  204.     // you can use the interrupt routine for non-busy wait (if the card enables interrupt
  205.     // indication for end of transfer).
  206.  
  207.     WD_DMAUnlock(hWD,&dma);
  208. }
  209.  
  210. // transfer data to/from PCI card NOT using DMA.
  211. // pBuffer if the data to transfer (or to receive data), dwBytes - size of data
  212. // fIsRead is TRUE for read (PCI card --> system memory), or FALSE for write ( memory --> PCI card)
  213. // addr local address on PCI card
  214. void IO_TransferBuffer(PVOID pBuffer, DWORD dwBytes, BOOL fIsRead, DWORD dwAddr)
  215. {
  216.     WD_TRANSFER trans;
  217.  
  218.     BZERO(trans);
  219.     if (fIsRead)
  220.         trans.cmdTrans = RM_SDWORD; // Read Memory String DWORD
  221.     else trans.cmdTrans = WM_SDWORD; // Write Memory String DWORD
  222.     trans.dwPort = G_baseMemoryTrns + dwAddr; 
  223.     trans.Data.pBuffer = pBuffer;
  224.     trans.dwBytes = dwBytes;
  225.  
  226.     // if fAutoinc==TRUE then read/write will run through an address range on the card
  227.     // if fAutoinc==FALSE then read/write will perform on the same address of the card
  228.     //    (usually used for FIFO where all reads/writes are to the same register)
  229.     trans.fAutoinc = TRUE; 
  230.  
  231.     trans.dwOptions = 0;
  232.  
  233.     WD_Transfer (hWD, &trans);
  234.  
  235.     // this function could also be implemeted directly with memcpy().
  236.     // for example, to read a memory region:
  237.     // memcpy (pBuffer, (PVOID) (dwAddr + G_baseMemory), dwBytes);
  238. }
  239.  
  240. int main(int argc, char *argv[])
  241. {
  242.     IO_Open();
  243.  
  244.     IO_DetectCard();
  245.  
  246.     // call your main card routine program
  247.     // in your program you can use IO_DMATransferBuffer() for DMA read/write,
  248.     // or IO_TransferBuffer() to do the same thing without DMA,
  249.     // IO_Read32BitRegister() & IO_Write32BitRegister for single 32bit read/write
  250.     MY_CardMainDriver(); 
  251.  
  252.     IO_Close();
  253.  
  254.     return 0;
  255. }
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.